#pragma once
#ifndef __G_MESSAGE_MANAGER_H__
#define __G_MESSAGE_MANAGER_H__


#include <vector>
#include <utility>
#include <unordered_map>

#include "GTypes.h"
#include "Gsingleton.h"
#include "GInitializable.h"

#define G_MAX_BUFFERED_MSG_COUNT	1024

namespace GEngine
{
	class GSystemMessage
	{
	public:
		GUInt32 Message;
		
		GSize	Parameter0; // wParam
		GSSize	Parameter1;	// lParam
		
		void*	UserData;

		GSystemMessage()
		{
			Message = 0;
			Parameter0 = 0;
			Parameter1 = 0;
			UserData = NULL;
		}

		GSystemMessage(GUInt32 Msg, GSize Param0, GSSize Param1, void* Data)
		{
			Message = Msg;
			Parameter0 = Param0;
			Parameter1 = Param1;
			UserData = Data;
		}

		~GSystemMessage()
		{
		}
	};

	class GWindow;
	class GMessageHandler;

	class GMessageManager : public GUtil::GInitializable, public GUtil::GSingleton<GMessageManager>
	{
	friend class GUtil::GSingleton<GMessageManager>;

	typedef std::vector<GWindow*> WindowArray;
	typedef std::vector<std::pair<GWindow*, GSystemMessage>> MessageArray;
	typedef std::unordered_multimap<GWindow*, GMessageHandler*> HandlerMap;

	private:
		bool			EnableDelay;

		HandlerMap		Handlers;
		MessageArray	Messages;

	protected:
						GMessageManager();
						~GMessageManager();

		void			DispatchMessages();

	public:
		GSize			GetHandlerCount() const;

		void			SetEnableDelay(bool Value);
		bool			GetEnableDelay() const;

		void			AppendHandler(GMessageHandler* Handler);
		void			RemoveHandler(GMessageHandler* Handler);

		bool			Update() PLATFORM;
		
		void			DelayedMessage(GWindow* Target, const GSystemMessage& Message);
		bool			InstantMessage(GWindow* Target, const GSystemMessage& Message);
		
		bool			Initialize() OVERRIDE;
		void			Uninitialize() OVERRIDE;

		static GUInt32	RegisterMessage(const char* MsgStr) PLATFORM;

	};
}

#define mGMessageManager	GEngine::GMessageManager::GetInstance()

#endif